/**
 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <glib.h>

#define SERVER_DATA_LEN     9216
#define BUFF_LEN            1024
#define MAX_CONNECT_NUM     10

static void recv_and_send(int c_fd, char *s)
{
    int ret;
    char buf[BUFF_LEN] = {0};

    while (1) {
        ret = recv(c_fd, buf, sizeof(buf), 0);
        if (ret <= 0) {
            printf("close\n");
            close(c_fd);
            break;
        }
        printf("recv client: %d, %s\n", c_fd, buf);
        ret = send(c_fd, s, SERVER_DATA_LEN, 0);
        if (ret <= 0) {
            printf("send fail\n");
            close(c_fd);
            break;
        }
        memset(buf, 0, BUFF_LEN);
    }

    return;
}

static void accept_func(int fd, char *s)
{
    int c_fd, pid;
    struct sockaddr_in c_addr;
    socklen_t socklen = sizeof(c_addr);
    char buf[BUFF_LEN] = {0};

    while (1) {
        c_fd = accept(fd, (struct sockaddr *)&c_addr, &socklen);
        if (c_fd > 0) {
            pid = fork();
            if (pid == 0) {
                recv_and_send(c_fd, s);
                _exit(0);
            }
        }
    }

    return;
}

int main(int argc, char *argv[])
{
    int fd;
    struct sockaddr_in s_addr;
    char *s;
    int port = (int)atoll(argv[1]);
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        return -1;
    }
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(port);
    s_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(fd, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1) {
        perror("bind error: %m");
        return -1;
    }
    listen(fd, MAX_CONNECT_NUM);

    s = g_malloc0(SERVER_DATA_LEN);

    memset(s, 'a', SERVER_DATA_LEN - 1);
    printf("server data len = %ud \n", strlen(s));

    accept_func(fd, s);

    g_free(s);
    return 0;
}
